/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.tbp.persitence.dao.impl;

import br.com.tbp.exception.PersistenciaException;
import br.com.tbp.model.domain.Boc;
import br.com.tbp.model.domain.Consultor;
import br.com.tbp.model.domain.Empresa;
import br.com.tbp.model.domain.SituacaoExterna;
import br.com.tbp.model.domain.ItemDePedido;
import br.com.tbp.model.domain.Pedido;
import br.com.tbp.model.domain.Produto;
import br.com.tbp.model.domain.StatusPedido;
import br.com.tbp.model.domain.SituacaoInterna;
import br.com.tbp.model.domain.Supervisor;
import br.com.tbp.model.domain.constant.CondicaoDaLinha;
import br.com.tbp.model.domain.constant.Departamento;
import br.com.tbp.persitence.FabricaDePersistencia;
import br.com.tbp.persitence.GerenciadorDeConexao;
import br.com.tbp.persitence.GerenciadorDeQuery;
import br.com.tbp.persitence.dao.PedidoDao;
import br.com.tbp.persitence.dao.SituacaoDoPedidoDao;
import br.com.tbp.utils.DateUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 *
 * @author Diego Freire
 */
public class PedidoDaoImpl implements PedidoDao {

    private Connection conn = null;
    private PreparedStatement pr = null;
    private ResultSet rs = null;

    public void registrar(Pedido p) throws PersistenciaException {
        if (p == null) {
            throw new PersistenciaException("Não foi informado o pedido a registrar.");
        }

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.insert"),
                    Statement.RETURN_GENERATED_KEYS);
            pr.setDate(1, DateUtils.dataObjetoParaDataBancoDeDados(p.getData()));
            pr.setLong(2, p.getConsultor() != null ? p.getConsultor().getId() : 0);
            pr.setLong(3, p.getEmpresa() != null ? p.getEmpresa().getId() : 0);
            pr.setLong(4, p.getSituacaoExternaAtual() != null ? p.getSituacaoExternaAtual().getId() : 0);
            pr.setInt(5, p.qtde_de_produtos());
            pr.setInt(6, p.qtde_de_itens());
            pr.setLong(7, p.getSupervisor() != null ? p.getSupervisor().getId() : 0);
            pr.setLong(8, p.getBoc() != null ? p.getBoc().getId() : 0);
            pr.setBoolean(9, p.isFinalizado());
            pr.setDate(10, DateUtils.dataObjetoParaDataBancoDeDados(p.getDataDeFinalizacao()));
            pr.setString(11, p.getBocInfo().getPlano());
            pr.setString(12, p.getBocInfo().getP2B());
            pr.setString(13, p.getBocInfo().getRadar());
            pr.setDate(14, DateUtils.dataObjetoParaDataBancoDeDados(p.getBocInfo().getDataInput()));

            pr.executeUpdate();

            rs = pr.getGeneratedKeys();
            rs.next();
            long id = rs.getLong(1);
            p.setId(id);

            this.salvaItensDoPedido(p);
            this.salvaSituacoesInternasDoPedido(p);
            this.salvaSituacoesExternasDoPedido(p);

        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível registrar o pedido.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
    }

    private void salvaItensDoPedido(Pedido p) throws PersistenciaException {
        try {
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.clean.itens"));
            pr.setLong(1, p.getId());
            pr.executeUpdate();

            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.insert.itens"));
            List<ItemDePedido> lista = p.getListaDeItensDoPedido();
            for (ItemDePedido item : lista) {
                pr.setLong(1, item.getProduto().getId());
                pr.setInt(2, item.getQtde());
                pr.setString(3, item.getCondicao().name());
                pr.setBoolean(4, item.isPortIn());
                pr.setInt(5, item.getQtePortIn());
                pr.setLong(6, p.getId());
                pr.setDate(7, item.getDataAtivacao() != null ? new java.sql.Date(item.getDataAtivacao().getTime()) : null);
                pr.setInt(8, item.getQtdeAtivada());
                pr.executeUpdate();
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível registrar os itens do pedido.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        }
    }

    private void salvaSituacoesExternasDoPedido(Pedido p) throws PersistenciaException {
        try {
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.clean.historico"));
            pr.setLong(1, p.getId());
            pr.executeUpdate();

            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.insert.historico"));
            List<SituacaoExterna> lista = p.getListaDeSituacoesExternas();
            for (SituacaoExterna s : lista) {
                pr.setLong(1, s.getSituacao().getId());
                pr.setDate(2, DateUtils.dataObjetoParaDataBancoDeDados(s.getData()));
                pr.setString(3, s.getObservacoes());
                pr.setLong(4, p.getId());
                pr.setBoolean(5, s.isAtual());
                pr.executeUpdate();
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível registrar o histórico do pedido.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        }
    }

    private void salvaSituacoesInternasDoPedido(Pedido p) throws PersistenciaException {
        try {
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.clean.situacoes.internas"));
            pr.setLong(1, p.getId());
            pr.executeUpdate();

            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.insert.situacao.interna"));
            List<SituacaoInterna> lista = p.getListaDeSituacoesInternas();
            for (SituacaoInterna s : lista) {
                pr.setString(1, s.getDepartamento().name());
                pr.setTimestamp(2, s.getDataDeEntrada());
                pr.setTimestamp(3, s.getDataDeSaida());
                pr.setInt(4, s.getTempoEmDias());
                pr.setBoolean(5, s.isAtual());
                pr.setString(6, s.getObservacoes());
                pr.setLong(7, p.getId());
                pr.executeUpdate();
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível registrar as situações internas.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        }
    }

    public Pedido pesquisar(long id) throws PersistenciaException {
        Pedido p = null;

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.id"));
            pr.setLong(1, id);
            rs = pr.executeQuery();
            if (rs != null) {
                if (rs.first()) {
                    p = this.criarPedido(rs, FabricaDePersistencia.createSituacaoDoPedidoDao());
                }
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível pesquisar o pedido.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return p;
    }

    private Pedido criarPedido(ResultSet rs, SituacaoDoPedidoDao dao_situacao) throws PersistenciaException {
        Pedido pedido = null;
        try {
            pedido = new Pedido(rs.getLong("id_pedido"));
            pedido.setData(DateUtils.dataBancoDeDadosParaDataObjeto(rs.getDate("data")));

            Consultor consultor = new Consultor(rs.getLong("id_consultor"), rs.getString("nome"));
            pedido.setConsultor(consultor);

            Empresa empresa = new Empresa(rs.getLong("id_empresa"), rs.getString("nome_fantasia"), rs.getString("razao_social"), rs.getString("cnpj"));
            pedido.setEmpresa(empresa);
            Long situacaoId = rs.getLong("id_situacao");
            if (situacaoId > 0) {
                pedido.setSituacaoExternaAtual(dao_situacao.pesquisar(situacaoId));
            }
            Long supervisorId = rs.getLong("id_supervisor");
            if (supervisorId > 0) {
                pedido.setSupervisor(new Supervisor(supervisorId, rs.getString("SupervisorNome")));
            }
            Long bocId = rs.getLong("id_boc");
            if (bocId > 0) {
                pedido.setBoc(new Boc(bocId, rs.getString("BocNome")));
            }
            pedido.setFinalizado(rs.getBoolean("finalizado"));
            if (pedido.isFinalizado()) {
                pedido.setDataDeFinalizacao(DateUtils.dataBancoDeDadosParaDataObjeto(rs.getDate("data_finalizacao")));
            }
            pedido.getBocInfo().setPlano(rs.getString("plano"));
            pedido.getBocInfo().setP2B(rs.getString("p2b"));
            pedido.getBocInfo().setRadar(rs.getString("radar"));
            pedido.getBocInfo().setDataInput(DateUtils.dataBancoDeDadosParaDataObjeto(rs.getDate("data_input")));

        } catch (SQLException sqlex) {
            StringBuilder msg = new StringBuilder("Não foi possível obter os dados do pedido.");
            msg.append("\nMotivo: ").append(sqlex.getMessage());
            throw new PersistenciaException(msg.toString());
        }
        return pedido;
    }

    public List<Pedido> pesquisarPelaEmpresa(String nome) throws PersistenciaException {
        List<Pedido> lista = new ArrayList<Pedido>();

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.empresa"));
            pr.setString(1, "%" + nome + "%");
            rs = pr.executeQuery();
            if (rs != null) {
                SituacaoDoPedidoDao dao_situacao = FabricaDePersistencia.createSituacaoDoPedidoDao();
                while (rs.next()) {
                    Pedido p = this.criarPedido(rs, dao_situacao);
                    lista.add(p);
                }
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível pesquisar os pedidos.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return lista;
    }

    public List<Pedido> pesquisarPeloCnpj(String cnpj) throws PersistenciaException {
        List<Pedido> lista = new ArrayList<Pedido>();

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.cnpj"));
            pr.setString(1, cnpj);
            rs = pr.executeQuery();
            if (rs != null) {
                SituacaoDoPedidoDao dao_situacao = FabricaDePersistencia.createSituacaoDoPedidoDao();
                while (rs.next()) {
                    Pedido p = this.criarPedido(rs, dao_situacao);
                    lista.add(p);
                }
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível pesquisar os pedidos.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return lista;
    }

    public List<Pedido> pesquisarPelaSituacao(StatusPedido s) throws PersistenciaException {
        List<Pedido> lista = new ArrayList<Pedido>();

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.situacao"));
            pr.setString(1, "%" + s.getNome() + "%");
            rs = pr.executeQuery();
            if (rs != null) {
                SituacaoDoPedidoDao dao_situacao = FabricaDePersistencia.createSituacaoDoPedidoDao();
                while (rs.next()) {
                    Pedido p = this.criarPedido(rs, dao_situacao);
                    lista.add(p);
                }
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível pesquisar os pedidos.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return lista;
    }

    public List<Pedido> pesquisar(Date d1, Date d2) throws PersistenciaException {
        List<Pedido> lista = new ArrayList<Pedido>();
        if (d1 == null) {
            return lista;
        }
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.datas"));
            pr.setDate(1, DateUtils.dataObjetoParaDataBancoDeDados(d1));
            pr.setDate(2, DateUtils.dataObjetoParaDataBancoDeDados(d1));
            rs = pr.executeQuery();
            if (rs != null) {
                SituacaoDoPedidoDao dao_situacao = FabricaDePersistencia.createSituacaoDoPedidoDao();
                while (rs.next()) {
                    Pedido p = this.criarPedido(rs, dao_situacao);
                    lista.add(p);
                }
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível pesquisar os pedidos.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return lista;
    }

    public List<Pedido> pesquisar(int limit_1, int limit_2) throws PersistenciaException {
        List<Pedido> lista = new ArrayList<Pedido>();

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.limit"));
            pr.setInt(1, limit_1);
            pr.setInt(2, limit_2);
            rs = pr.executeQuery();
            if (rs != null) {
                SituacaoDoPedidoDao dao_situacao = FabricaDePersistencia.createSituacaoDoPedidoDao();
                while (rs.next()) {
                    Pedido p = this.criarPedido(rs, dao_situacao);
                    lista.add(p);
                }
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível pesquisar os pedidos.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return lista;
    }

    public void removerPedidoPelaEmpresa(Empresa e) throws PersistenciaException {
        if (e == null) {
            throw new PersistenciaException("Não foi informado a empresa.");
        }
        List<Long> listaDeIds = null;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.pela.empresa"));
            pr.setLong(1, e.getId());
            rs = pr.executeQuery();
            if (rs != null) {
                listaDeIds = new ArrayList<Long>();
                while (rs.next()) {
                    listaDeIds.add(rs.getLong("id_pedido"));
                }
            }

            this.remover(listaDeIds);

        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível remover os pedidos pela empresa.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
    }

    public void remover(long id) throws PersistenciaException {
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.delete"));
            pr.setLong(1, id);
            pr.executeUpdate();

            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.delete.itens"));
            pr.setLong(1, id);
            pr.executeUpdate();

            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.delete.historico"));
            pr.setLong(1, id);
            pr.executeUpdate();
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível remover o pedido.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
    }

    public void remover(List<Long> listaDeIds) throws PersistenciaException {
        if ((listaDeIds == null) || (listaDeIds.isEmpty())) {
            return;
        }
        try {
            for (long pedidoId : listaDeIds) {
                pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.delete"));
                pr.setLong(1, pedidoId);
                pr.executeUpdate();

                pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.delete.itens"));
                pr.setLong(1, pedidoId);
                pr.executeUpdate();

                pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.delete.historico"));
                pr.setLong(1, pedidoId);
                pr.executeUpdate();
            }

        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível remover o pedido.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        }
    }

    public void removerPedidoPeloConsultor(Consultor c) throws PersistenciaException {
        if (c == null) {
            throw new PersistenciaException("Não foi informado o consultor.");
        }
        List<Long> listaDeIds = null;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.pelo.consultor"));
            pr.setLong(1, c.getId());
            rs = pr.executeQuery();
            if (rs != null) {
                listaDeIds = new ArrayList<Long>();
                while (rs.next()) {
                    listaDeIds.add(rs.getLong("id_pedido"));
                }
            }

            this.remover(listaDeIds);

        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível remover os pedidos pelo consultor.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
    }

    public List<Pedido> pesquisar() throws PersistenciaException {
        List<Pedido> lista = new ArrayList<Pedido>();

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.todos"));
            rs = pr.executeQuery();
            if (rs != null) {
                SituacaoDoPedidoDao dao_situacao = FabricaDePersistencia.createSituacaoDoPedidoDao();
                while (rs.next()) {
                    Pedido p = this.criarPedido(rs, dao_situacao);
                    lista.add(p);
                }
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível pesquisar os pedidos.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return lista;
    }

    public void recuperaItensDePedido(Pedido p) throws PersistenciaException {
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.itens"));
            pr.setLong(1, p.getId());
            rs = pr.executeQuery();

            if (rs != null) {
                while (rs.next()) {
                    ItemDePedido item = this.criarItemDePedido(rs);
                    p.addItem(item);
                }
            }

        } catch (SQLException sqle) {
            StringBuilder msg = new StringBuilder("Não foi possível recuperar os itens do pedido.");
            msg.append("\nMotivo: ").append(sqle.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
    }

    public void recuperaSituacoesExternasDoPedido(Pedido p) throws PersistenciaException {
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.situacoes.externas"));
            pr.setLong(1, p.getId());
            rs = pr.executeQuery();

            if (rs != null) {
                SituacaoDoPedidoDao dao_situacao = FabricaDePersistencia.createSituacaoDoPedidoDao();
                while (rs.next()) {
                    SituacaoExterna s = this.criarSituacaoExterna(rs, dao_situacao);
                    p.addSituacaoExternaAntiga(s);
                }
            }

        } catch (SQLException sqle) {
            StringBuilder msg = new StringBuilder("Não foi possível recuperar o histórico de situações externas do pedido.");
            msg.append("\nMotivo: ").append(sqle.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
    }

    private ItemDePedido criarItemDePedido(ResultSet rs) throws PersistenciaException {
        ItemDePedido item = null;
        try {
            Produto produto = new Produto(rs.getLong("id_produto"), rs.getString("nome"));
            item = new ItemDePedido(produto, rs.getInt("quantidade"));
            item.setCondicao(CondicaoDaLinha.converter(rs.getString("situacao")));
            item.setPortIn(rs.getBoolean("port_in"));
            item.setQtePortIn(rs.getInt("quantidade_portin"));
            item.setId(rs.getLong("id_item"));
            item.setDataAtivacao(DateUtils.dataBancoDeDadosParaDataObjeto(rs.getDate("data_ativacao")));
            item.setQtdeAtivada(rs.getInt("qtde_ativada"));
        } catch (SQLException sqle) {
            StringBuilder msg = new StringBuilder("Não foi possível obter os dados do item do pedido.");
            msg.append("\nMotivo: ").append(sqle.getMessage());
            throw new PersistenciaException(msg.toString());
        }
        return item;
    }

    private SituacaoExterna criarSituacaoExterna(ResultSet rs, SituacaoDoPedidoDao dao_situacao) throws PersistenciaException {
        SituacaoExterna s = null;
        try {
            s = new SituacaoExterna(rs.getLong("id_historico"));
            s.setData(DateUtils.dataBancoDeDadosParaDataObjeto(rs.getDate("data")));
            s.setObservacoes(rs.getString("observacoes"));
            s.setAtual(rs.getBoolean("atual"));
            s.setSituacao(dao_situacao.pesquisar(rs.getLong("id_situacao")));
        } catch (SQLException sqle) {
            StringBuilder msg = new StringBuilder("Não foi possível obter os dados do histórico do pedido.");
            msg.append("\nMotivo: ").append(sqle.getMessage());
            throw new PersistenciaException(msg.toString());
        }
        return s;
    }

    private SituacaoInterna criarSituacaoInterna(ResultSet rs) throws PersistenciaException {
        SituacaoInterna s = null;
        try {
            s = new SituacaoInterna(rs.getLong("id_situacao"));
            s.setDepartamento(Departamento.valueOf(rs.getString("departamento")));
            s.setDataDeEntrada(rs.getTimestamp("data_entrada"));
            s.setDataDeSaida(rs.getTimestamp("data_saida"));
            s.setAtual(rs.getBoolean("atual"));
            s.setObservacoes(rs.getString("observacoes"));
        } catch (SQLException sqle) {
            StringBuilder msg = new StringBuilder("Não foi possível obter os dados do histórico do pedido.");
            msg.append("\nMotivo: ").append(sqle.getMessage());
            throw new PersistenciaException(msg.toString());
        }
        return s;
    }

    public void atualizar(Pedido p) throws PersistenciaException {
        if (p == null) {
            throw new PersistenciaException("Não foi informado o pedido a atualizar.");
        }

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.update"));
            pr.setDate(1, DateUtils.dataObjetoParaDataBancoDeDados(p.getData()));
            pr.setLong(2, p.getSituacaoExternaAtual() != null ? p.getSituacaoExternaAtual().getId() : 0);
            pr.setInt(3, p.qtde_de_produtos());
            pr.setInt(4, p.qtde_de_itens());
            pr.setLong(5, p.getSupervisor() != null ? p.getSupervisor().getId() : 0);
            pr.setLong(6, p.getBoc() != null ? p.getBoc().getId() : 0);
            pr.setBoolean(7, p.isFinalizado());
            pr.setDate(8, DateUtils.dataObjetoParaDataBancoDeDados(p.getDataDeFinalizacao()));
            pr.setString(9, p.getBocInfo().getPlano());
            pr.setString(10, p.getBocInfo().getP2B());
            pr.setString(11, p.getBocInfo().getRadar());
            pr.setDate(12, DateUtils.dataObjetoParaDataBancoDeDados(p.getBocInfo().getDataInput()));
            pr.setLong(13, p.getId());

            pr.executeUpdate();

            this.salvaItensDoPedido(p);
            this.salvaSituacoesInternasDoPedido(p);
            this.salvaSituacoesExternasDoPedido(p);

        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível atualizar o pedido.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, null);
        }
    }

    public void recuperaSituacoesInternasDoPedido(Pedido p) throws PersistenciaException {
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.situacoes.internas"));
            pr.setLong(1, p.getId());
            rs = pr.executeQuery();

            if (rs != null) {
                while (rs.next()) {
                    SituacaoInterna s = this.criarSituacaoInterna(rs);
                    p.addSituacaoInternaAntiga(s);
                }
            }

        } catch (SQLException sqle) {
            StringBuilder msg = new StringBuilder("Não foi possível recuperar o as situações internas do pedido.");
            msg.append("\nMotivo: ").append(sqle.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
    }

    public int buscaTotalPorCondicao(CondicaoDaLinha c, Date inicio, Date fim) throws PersistenciaException {
        int total = 0;

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.linhas.condicao"));
            pr.setDate(1, DateUtils.dataObjetoParaDataBancoDeDados(inicio));
            if (fim != null) {
                pr.setDate(2, DateUtils.dataObjetoParaDataBancoDeDados(fim));
            } else {
                pr.setDate(2, DateUtils.dataObjetoParaDataBancoDeDados(inicio));
            }
            pr.setString(3, c.name());
            rs = pr.executeQuery();
            if (rs.first()) {
                total = rs.getInt("total");
            }

        } catch (SQLException sqle) {
            StringBuilder msg = new StringBuilder("Não foi possível recuperar a quantidade de linhas por condição.");
            msg.append("\nMotivo: ").append(sqle.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return total;
    }

    public int buscaTotalPortIn(Date inicio, Date fim) throws PersistenciaException {
        int total = 0;

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.portin"));
            pr.setDate(1, DateUtils.dataObjetoParaDataBancoDeDados(inicio));
            if (fim != null) {
                pr.setDate(2, DateUtils.dataObjetoParaDataBancoDeDados(fim));
            } else {
                pr.setDate(2, DateUtils.dataObjetoParaDataBancoDeDados(inicio));
            }
            rs = pr.executeQuery();
            if (rs.first()) {
                total = rs.getInt("total");
            }

        } catch (SQLException sqle) {
            StringBuilder msg = new StringBuilder("Não foi possível recuperar a quantidade de linhas port-in.");
            msg.append("\nMotivo: ").append(sqle.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return total;
    }

    public List<ItemDePedido> getAtivacoesPelaData(Date _1, Date _2) throws PersistenciaException {
        List<ItemDePedido> lista = new ArrayList<ItemDePedido>();

        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT PR.ID_PRODUTO, PR.NOME, I.QUANTIDADE, I.PORT_IN, I.QUANTIDADE_PORTIN, I.ID_ITEM, I.DATA_ATIVACAO, I.QTDE_ATIVADA, P.ID_PEDIDO, P.DATA, E.RAZAO_SOCIAL, C.NOME AS CONSULTOR, B.NOME AS BOC FROM ITENS_PEDIDO I INNER JOIN PRODUTO PR ON I.ID_PRODUTO = PR.ID_PRODUTO INNER JOIN PEDIDO P ON I.ID_PEDIDO = P.ID_PEDIDO INNER JOIN EMPRESA E ON P.ID_EMPRESA = E.ID_EMPRESA INNER JOIN CONSULTOR C ON P.ID_CONSULTOR = C.ID_CONSULTOR INNER JOIN BOC B ON P.ID_BOC = B.ID_BOC WHERE P.DATA BETWEEN ? AND ? ORDER BY P.DATA DESC;");
            pr.setDate(1, new java.sql.Date(_1.getTime()));
            pr.setDate(2, new java.sql.Date(_2.getTime()));
            rs = pr.executeQuery();

            if (rs != null) {
                while (rs.next()) {
                    ItemDePedido item = new ItemDePedido(new Produto(rs.getLong("ID_PRODUTO"), rs.getString("NOME")),
                            rs.getInt("QUANTIDADE"), rs.getBoolean("PORT_IN"), rs.getInt("QUANTIDADE_PORTIN"));
                    item.setId(rs.getLong("ID_ITEM"));
                    item.setDataAtivacao(rs.getDate("DATA_ATIVACAO") != null ? new Date(rs.getDate("DATA_ATIVACAO").getTime()) : new Date());
                    item.setQtdeAtivada(rs.getInt("QTDE_ATIVADA"));
                    Pedido pedido = new Pedido();
                    pedido.setId(rs.getLong("ID_PEDIDO"));
                    pedido.setData(new Date(rs.getDate("DATA").getTime()));
                    pedido.setEmpresa(new Empresa(rs.getString("RAZAO_SOCIAL")));
                    pedido.setConsultor(new Consultor(rs.getString("CONSULTOR")));
                    pedido.setBoc(new Boc(rs.getString("BOC")));
                    item.setPedido(pedido);
                    lista.add(item);
                }
            }

        } catch (SQLException sqle) {
            StringBuilder msg = new StringBuilder("Não foi possível listar as ativações pela data.");
            msg.append("\nMotivo: ").append(sqle.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return lista;
    }

    public void atualizarAtivacoes(List<ItemDePedido> itensList) throws PersistenciaException {
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("UPDATE ITENS_PEDIDO SET DATA_ATIVACAO=?, QTDE_ATIVADA=? WHERE ID_ITEM=?");
            for (ItemDePedido item : itensList) {
                pr.setDate(1, item.getDataAtivacao() != null ? new java.sql.Date(item.getDataAtivacao().getTime()) : null);
                pr.setInt(2, item.getQtdeAtivada());
                pr.setLong(3, item.getId());
                pr.executeUpdate();
            }
        } catch (SQLException sqle) {
            StringBuilder msg = new StringBuilder("Não foi possível atualizar as ativações.");
            msg.append("\nMotivo: ").append(sqle.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
    }

    public Pedido pesquisar(long id, Consultor consultor) throws PersistenciaException {
        Pedido p = null;

        try {
            conn = GerenciadorDeConexao.abreConexao();
            if (consultor != null) {
                pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.id.consultor"));
                pr.setLong(1, id);
                pr.setLong(2, consultor.getId());
            } else {
                pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.id"));
                pr.setLong(1, id);
            }
            rs = pr.executeQuery();
            if (rs != null) {
                if (rs.first()) {
                    p = this.criarPedido(rs, FabricaDePersistencia.createSituacaoDoPedidoDao());
                }
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível pesquisar o pedido.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return p;
    }

    public List<Pedido> pesquisarPelaEmpresa(String nome, Consultor consultor) throws PersistenciaException {
        List<Pedido> lista = new ArrayList<Pedido>();

        try {
            conn = GerenciadorDeConexao.abreConexao();
            if (consultor != null) {
                pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.empresa.consultor"));
                pr.setString(1, "%" + nome + "%");
                pr.setLong(2, consultor.getId());
            } else {
                pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.empresa"));
                pr.setString(1, "%" + nome + "%");
            }
            rs = pr.executeQuery();
            if (rs != null) {
                SituacaoDoPedidoDao dao_situacao = FabricaDePersistencia.createSituacaoDoPedidoDao();
                while (rs.next()) {
                    Pedido p = this.criarPedido(rs, dao_situacao);
                    lista.add(p);
                }
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível pesquisar os pedidos.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return lista;
    }

    public List<Pedido> pesquisarPeloCnpj(String cnpj, Consultor consultor) throws PersistenciaException {
        List<Pedido> lista = new ArrayList<Pedido>();

        try {
            conn = GerenciadorDeConexao.abreConexao();
            if (consultor != null) {
                pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.cnpj.consultor"));
                pr.setString(1, cnpj);
                pr.setLong(2, consultor.getId());
            } else {
                pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.cnpj"));
                pr.setString(1, cnpj);
            }
            rs = pr.executeQuery();
            if (rs != null) {
                SituacaoDoPedidoDao dao_situacao = FabricaDePersistencia.createSituacaoDoPedidoDao();
                while (rs.next()) {
                    Pedido p = this.criarPedido(rs, dao_situacao);
                    lista.add(p);
                }
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível pesquisar os pedidos.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return lista;
    }

    public List<Pedido> pesquisar(Date d1, Date d2, Consultor consultor) throws PersistenciaException {
        List<Pedido> lista = new ArrayList<Pedido>();
        if (d1 == null) {
            return lista;
        }
        try {
            conn = GerenciadorDeConexao.abreConexao();
            if (consultor != null) {
                pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.datas.consultor"));
                pr.setDate(1, DateUtils.dataObjetoParaDataBancoDeDados(d1));
                pr.setDate(2, DateUtils.dataObjetoParaDataBancoDeDados(d2));
                pr.setLong(3, consultor.getId());
            } else {
                pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.datas"));
                pr.setDate(1, DateUtils.dataObjetoParaDataBancoDeDados(d1));
                pr.setDate(2, DateUtils.dataObjetoParaDataBancoDeDados(d2));
            }
            rs = pr.executeQuery();
            if (rs != null) {
                SituacaoDoPedidoDao dao_situacao = FabricaDePersistencia.createSituacaoDoPedidoDao();
                while (rs.next()) {
                    Pedido p = this.criarPedido(rs, dao_situacao);
                    lista.add(p);
                }
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível pesquisar os pedidos.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    public List<Pedido> pesquisar(int limit_1, int limit_2, Consultor consultor) throws PersistenciaException {
        List<Pedido> lista = new ArrayList<Pedido>();

        try {
            conn = GerenciadorDeConexao.abreConexao();
            if (consultor != null) {
                pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.limit.consultor"));
                pr.setLong(1, consultor.getId());
                pr.setInt(2, limit_1);
                pr.setInt(3, limit_2);
            } else {
                pr = conn.prepareStatement(GerenciadorDeQuery.getQuery("pedido.select.limit"));
                pr.setInt(1, limit_1);
                pr.setInt(2, limit_2);
            }
            rs = pr.executeQuery();
            if (rs != null) {
                SituacaoDoPedidoDao dao_situacao = FabricaDePersistencia.createSituacaoDoPedidoDao();
                while (rs.next()) {
                    Pedido p = this.criarPedido(rs, dao_situacao);
                    lista.add(p);
                }
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível pesquisar os pedidos.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }

        return lista;
    }
}
